package com.easy.app.controller.monitor;

import com.alibaba.fastjson2.JSON;
import com.easy.framework.common.constant.Constants;
import com.easy.framework.common.model.R;
import com.easy.framework.common.utils.Func;
import com.easy.module.system.model.CacheModel;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 缓存监控
 *
 * @author Easy
 */
@RequiredArgsConstructor
@RestController
@RequestMapping("/monitor/cache")
public class CacheController {

    private final RedisTemplate<String, String> redisTemplate;

    @PreAuthorize("@perm.hasPermission('cache$list')")
    @GetMapping("/getValue/{cacheName}/{cacheKey}")
    public R<CacheModel> getCacheValue(@PathVariable("cacheName") String cacheName, @PathVariable("cacheKey") String cacheKey) {
        String cacheValue = redisTemplate.opsForValue().get(cacheKey);
        CacheModel cacheModel = new CacheModel(cacheName, cacheKey, cacheValue);
        return R.success(cacheModel);
    }

    @PreAuthorize("@perm.hasPermission('cache$remove')")
    @DeleteMapping("/clearCacheName/{cacheName}")
    public R clearCacheName(@PathVariable("cacheName") String cacheName) {
        Collection<String> cacheKeys = redisTemplate.keys(cacheName + "*");
        redisTemplate.delete(cacheKeys);
        return R.success();
    }

    @PreAuthorize("@perm.hasPermission('cache$remove')")
    @DeleteMapping("/clearCacheKey/{cacheKey}")
    public R clearCacheKey(@PathVariable("cacheKey") String cacheKey) {
        redisTemplate.delete(cacheKey);
        return R.success();
    }

    @PreAuthorize("@perm.hasPermission('cache$remove')")
    @DeleteMapping("/clearCacheAll")
    public R clearCacheAll() {
        Collection<String> cacheKeys = redisTemplate.keys("*");
        redisTemplate.delete(cacheKeys);
        return R.success();
    }

    @GetMapping("/keys")
    public R keys(@RequestParam(value = "cacheName" ,required = false) String cacheName) {
        if (Func.isEmpty(cacheName)) {
            cacheName = Constants.CACHE;
        }
        Set<String> keys = redisTemplate.keys(cacheName + "*");

        TreeSet<String> childrenKeys = new TreeSet<>();
        TreeSet<String> allKeys = new TreeSet<>();
        for (String key : keys) {
            String s[] = key.replace(cacheName, "").split("\\:");
            StringBuffer sb = new StringBuffer(cacheName);
            boolean flag=true;
            for(int i=0;i<s.length;i++){
                if(i<s.length-1){
                    sb.append(s[i].concat(":"));
                }else{
                    sb.append(s[i]);
                }
                if(keys.stream().filter(k->k.indexOf(sb.toString())>-1).count() > 1||allKeys.contains(sb.toString())){
                    flag = false;
                }
            }
            if(flag){
                childrenKeys.add(key.replace(cacheName,""));
                allKeys.add(key);
            }else{
                if (s.length == 1) {
                    childrenKeys.add(s[0]);
                    allKeys.add(cacheName+s[0]);
                } else if (Func.isNotEmpty(s[0])) {
                    if (s.length > 1 && Func.isEmpty(s[1])) {
                        childrenKeys.add(s[0] + "::");
                        allKeys.add(cacheName+s[0] + "::");
                    } else {
                        childrenKeys.add(s[0] + ":");
                        allKeys.add(cacheName+s[0] + ":");
                    }
                }
            }
        }
        List<Map<String, Object>> childrenList = new ArrayList<>();
        for (String key : childrenKeys) {
            Map<String, Object> childMap = new HashMap<>();
            childMap.put("key", cacheName + key);
            childMap.put("label", key);
            childMap.put("isLeaf", !key.substring(key.length()-1).equals(":"));
            childMap.put("cacheName", cacheName);
            childrenList.add(childMap);
        }
        System.out.println(JSON.toJSONString(childrenList));
        return R.success(childrenList);
    }

}
